package com.shuai.baibi.controller;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.shuai.baibi.manager.RedissonManager;
import com.shuai.baibi.manager.XunFeiAPIManager;
import com.shuai.baibi.manager.YuAIManager;
import com.shuai.baibi.common.BaseResponse;
import com.shuai.baibi.common.ErrorCode;
import com.shuai.baibi.constant.FileConstant;
import com.shuai.baibi.constant.UserConstant;
import com.shuai.baibi.exception.BusinessException;
import com.shuai.baibi.model.dto.chart.ChartRequest;
import com.shuai.baibi.model.entity.Chart;
import com.shuai.baibi.model.enums.ChartStatusEnum;
import com.shuai.baibi.model.vo.ChartVO;
import com.shuai.baibi.model.vo.UserVO;
import com.shuai.baibi.mq.BIChartMessageMQProducer;
import com.shuai.baibi.service.ChartService;
import com.shuai.baibi.service.FileService;
import com.shuai.baibi.utils.ExcelHandleUtils;
import com.shuai.baibi.utils.ResultUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.net.URISyntaxException;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadPoolExecutor;

@RestController
@RequestMapping("/chart")
@Slf4j
public class ChartController {
    @Autowired
    private ChartService chartService;
    @Autowired
    private YuAIManager yuAIManager;
    @Autowired
    private RedissonManager redissonManager;
    @Autowired
    private ThreadPoolExecutor threadPoolExecutor;
    @Autowired
    private XunFeiAPIManager xunFeiAPIManager;
    @Autowired
    private BIChartMessageMQProducer messageMQProducer;
    @Autowired
    private FileService fileService;
    private static final long AI_ID = 1659171950288818178L;


    /**
     * 同步处理用户的图标哦分析请求
     */
    @RequestMapping(value = "/file", method = RequestMethod.POST)
    public BaseResponse<ChartVO> aiAnalysisToGenChartData(@RequestPart("file") MultipartFile multipartFile, ChartRequest chartRequest, HttpServletRequest request) {
        String goal = chartRequest.getGoal();
        String name = chartRequest.getName();
        if (name == null) {
            name = "<未设置图表名称>";
        }
        String chartType = chartRequest.getChartType();
        if (chartType == null) {
            chartType = "<未设置图表类型>";
        }
        if (multipartFile == null || multipartFile.getSize() <= 0 || StringUtils.isBlank(goal)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!fileService.checkFileStyle(multipartFile)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件格式错误或大小超限(" + FileConstant.FILE_SIZE_MB + ")");
        }
        if (name.length() > 100) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "指定图表名称过长");
        }
        UserVO user = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
        // 对用户的请求进行限流
        redissonManager.doRate(String.valueOf(user.getId()));   // 针对用户id分发限流器
        // 将excel文件转换为字符串
        String csvStr = ExcelHandleUtils.handleExcelToStr(multipartFile);
        String askStr = this.buildAskStr(goal, chartType, csvStr);
        // 调用AI接口并取得返回结果
        String responseMessage = yuAIManager.requestAIWithParams(AI_ID, askStr);
        // 对相应数据进行处理
        Map<String, String> responseMap = this.processResponseData(responseMessage);
        // 保存图表数据
        Chart chart = new Chart();
        chart.setName(name);
        chart.setGoal(goal);
        chart.setChartType(chartType);
        chart.setChartData(csvStr);
        chart.setStatus(ChartStatusEnum.SUCCEED.getStatus());
        chart.setGenChartData(responseMap.get("genChartData"));
        chart.setGenChartResult(responseMap.get("genChartResult"));
        chart.setUserId(user.getId());
        if (!chartService.save(chart)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "图表数据保存失败");
        }
        // 返回生成的图表数据分析结果
        ChartVO chartVO = new ChartVO();
        BeanUtils.copyProperties(chart, chartVO);
        return ResultUtils.success(chartVO);
    }


    /**
     * 异步处理用户请求接口（线程池 + 调用讯飞大模型接口）
     */
    @RequestMapping(value = "/file/async", method = RequestMethod.POST)
    public BaseResponse<ChartVO> aiAnalysisToGenChartDataAsync(@RequestPart("file") MultipartFile multipartFile,
                                                               ChartRequest chartRequest,
                                                               HttpServletRequest request) {
        String goal = chartRequest.getGoal();
        String name = chartRequest.getName();
        if (name == null) {
            name = "<未设置图表名称>";
        }
        String chartType = chartRequest.getChartType();
        if (chartType == null) {
            chartType = "<未设置图表类型>";
        }
        if (multipartFile == null || multipartFile.getSize() <= 0 || StringUtils.isBlank(goal)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!fileService.checkFileStyle(multipartFile)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件格式错误或大小超限(" + FileConstant.FILE_SIZE_MB + ")");
        }
        if (name.length() > 100) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "指定图表名称过长");
        }
        UserVO user = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
        // 对用户的请求进行限流
        redissonManager.doRate(String.valueOf(user.getId()));   // 针对用户id分发限流器

        Chart chart = new Chart();
        chart.setUserId(user.getId());
        chart.setName(name);
        chart.setGoal(goal);
        chart.setChartType(chartType);
        // 将excel文件转换为csv字符串
        String csvStr = ExcelHandleUtils.handleExcelToStr(multipartFile);
        chart.setChartData(csvStr);
        chart.setStatus(ChartStatusEnum.WAITING.getStatus());
        // 将用户的分析图表请求保存到数据库中，并设置状态为等待中-waiting-0
        if (!chartService.save(chart)) {
            log.error("【" + LocalDateTime.now() + "】error-数据库服务异常-保存chart" + ChartController.class);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在加急修复中...");
        }
        // 根据用户请求转换为对AI的标准请求格式
//        String askStr = this.buildXFAskStr(goal, chartType, csvStr);
        String askStr = chartService.buildXFAskStr(goal, chartType, csvStr);
        // 启动新线程调用AI接口API
        CompletableFuture.runAsync(new Runnable() {
            @Override
            public void run() {
                // 先更新图表分析表中的数据为running-1处理中状态
                chart.setStatus(ChartStatusEnum.RUNNING.getStatus());
                if (!chartService.updateById(chart)) {
                    log.error("【" + LocalDateTime.now() + "】error-数据库服务异常-保存chart" + ChartController.class);
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在加急修复中...");
                }
                String responseMessage = null;
                Map<String, String> responseMap = null;
                // 调用AI接口并取得返回结果
                try {
                    responseMessage = xunFeiAPIManager.ask(askStr);
                } catch (Exception e) {
                    log.error("[" + LocalDateTime.now() + "]调用AI请求分析图表出错,图表数据：" + chart);
                    // 更新图表信息表中的图表状态为2-failed
                    chart.setStatus(ChartStatusEnum.FAILED.getStatus());
                    chartService.setExecMessage(chart, "分析图表数据失败，请尝试重新提交（-1）");
                    return;
                }
                // 对相应数据进行处理
                try {
                    responseMap = chartService.processXFResponseData(responseMessage);
                } catch (Exception e) {
                    log.error("[" + LocalDateTime.now() + "]AI响应数据格式异常：" + chart);
                    // 更新图表信息表中的图表状态为2-failed
                    chart.setStatus(ChartStatusEnum.FAILED.getStatus());
                    chartService.setExecMessage(chart, "分析图表数据失败，请尝试重新提交（-2）");
                    return;
                }
                if (responseMap == null) {
                    log.error("【" + LocalDateTime.now() + "】error-AI接口响应数据格式错误" + ChartController.class);
                    chartService.setExecMessage(chart, "分析图标数据失败，请尝试重新提交（-3）");
                    return;
                }
                // 保存图表数据
                chart.setStatus(ChartStatusEnum.SUCCEED.getStatus());
                chart.setGenChartData(responseMap.get("genChartData"));
                chart.setGenChartResult(responseMap.get("genChartResult"));
//                chart.setStatus(ChartStatusEnum.SUCCEED.getStatus());
                if (!chartService.updateById(chart)) {
                    throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在快马加鞭修复中...");
                }
            }


        }, threadPoolExecutor);

        // 返回生成的图表数据分析结果
        ChartVO chartVO = new ChartVO();
        BeanUtils.copyProperties(chart, chartVO);
        return ResultUtils.success(chartVO);
    }


    /**
     * 异步处理用户请求接口（消息队列 + 调用讯飞大模型接口）
     */
    @RequestMapping(value = "/file/async/mq", method = RequestMethod.POST)
    public BaseResponse<ChartVO> aiAnalysisToGenChartDataAsyncMQ(@RequestPart("file") MultipartFile multipartFile,
                                                                 ChartRequest chartRequest,
                                                                 HttpServletRequest request) {

        String goal = chartRequest.getGoal();
        String name = chartRequest.getName();
        if (name == null) {
            name = "<未设置图表名称>";
        }
        String chartType = chartRequest.getChartType();
        if (chartType == null) {
            chartType = "<未设置图表类型>";
        }
        if (multipartFile == null || multipartFile.getSize() <= 0 || StringUtils.isBlank(goal)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        if (!fileService.checkFileStyle(multipartFile)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件格式错误或大小超限(" + FileConstant.FILE_SIZE_MB + ")");
        }
        if (name.length() > 100) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "指定图表名称过长");
        }
        UserVO user = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
        // 对用户的请求进行限流
        redissonManager.doRate(String.valueOf(user.getId()));   // 针对用户id分发限流器

        Chart chart = new Chart();
        chart.setUserId(user.getId());
        chart.setName(name);
        chart.setGoal(goal);
        chart.setChartType(chartType);


        // 将excel文件转换为csv字符串
        String csvStr = ExcelHandleUtils.handleExcelToStr(multipartFile);
        chart.setChartData(csvStr);
        chart.setStatus(ChartStatusEnum.WAITING.getStatus());
        // 将用户的分析图表请求保存到数据库中，并设置状态为等待中-waiting-0
        if (!chartService.save(chart)) {
            log.error("【" + LocalDateTime.now() + "】error-数据库服务异常-保存chart" + ChartController.class);
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在加急修复中...");
        }


        // 将用户上传的文件持久化，保存记录到数据库chart_annex表当中
        try {
            fileService.uploadFile(multipartFile, chart);
        } catch (IOException | URISyntaxException e) {
            chartService.removeById(chart.getId());
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());
        }

        // 将消息编码传送进消息队列
        Long chartId = chart.getId();
        messageMQProducer.sendMessage(String.valueOf(chartId));

        // 返回用户上柴男图表的id登原始信息
        ChartVO chartVO = new ChartVO();
        BeanUtils.copyProperties(chart, chartVO);
        return ResultUtils.success(chartVO);
    }


    //    /**
//     * 异步处理用户请求(调用yu-ai模型接口)
//     *
//     * @return
//     */
//    @RequestMapping(value = "/file/async", method = RequestMethod.POST)
//    public BaseResponse<ChartVO> aiAnalysisToGenChartDataAsync(@RequestPart("file") MultipartFile multipartFile,
//                                                               ChartRequest chartRequest,
//                                                               HttpServletRequest request) {
//        String goal = chartRequest.getGoal();
//        String name = chartRequest.getName();
//        if (name == null) {
//            name = "<未设置图表名称>";
//        }
//        String chartType = chartRequest.getChartType();
//        if (chartType == null) {
//            chartType = "<未设置图表类型>";
//        }
//        if (multipartFile == null || multipartFile.getSize() <= 0 || StringUtils.isBlank(goal)) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR);
//        }
//        if (!this.checkFileStyle(multipartFile)) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR, "文件格式错误或大小超限(" + FileConstant.ANALYSIS_FILE_SIZE + "MB)");
//        }
//        if (name.length() > 100) {
//            throw new BusinessException(ErrorCode.PARAMS_ERROR, "指定图表名称过长");
//        }
//        UserVO user = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
//        // 对用户的请求进行限流
//        redissonManager.doRate(String.valueOf(user.getId()));   // 针对用户id分发限流器
//
//        Chart chart = new Chart();
//        chart.setUserId(user.getId());
//        chart.setName(name);
//        chart.setGoal(goal);
//        chart.setChartType(chartType);
//        // 将excel文件转换为csv字符串
//        String csvStr = ExcelHandleUtils.handleExcelToStr(multipartFile);
//        chart.setChartData(csvStr);
//        chart.setStatus(ChartStatusEnum.WAITING.getStatus());
//        // 将用户的分析图表请求保存到数据库中，并设置状态为等待中-waiting-0
//        chartService.save(chart);
//        // 根据用户请求转换为对AI的标准请求格式
//        String askStr = this.buildAskStr(goal, chartType, csvStr);
//
//        // 启动新线程调用AI接口API
//        CompletableFuture.runAsync(new Runnable() {
//            @Override
//            public void run() {
//                // 先更新图表分析表中的数据为running-1处理中状态
//                chart.setStatus(ChartStatusEnum.RUNNING.getStatus());
//                chartService.updateById(chart);
//                String responseMessage = null;
//                Map<String, String> responseMap = null;
////                try {
//                // 调用AI接口并取得返回结果
//                try {
//                    responseMessage = yuAIManager.requestAIWithParams(AI_ID, askStr);
//                } catch (Exception e) {
//                    log.error("[" + LocalDateTime.now() + "]调用AI请求分析图表出错,图表数据：" + chart);
//                    // 更新图表信息表中的图表状态为2-failed
//                    chart.setStatus(ChartStatusEnum.FAILED.getStatus());
//                    setExecMessage(chart, "分析图表数据失败，请尝试重新提交（-1）");
//                    return;
//                }
////                System.out.println(responseMessage);
//                // 对相应数据进行处理
//                try {
//                    responseMap = processResponseData(responseMessage);
//                } catch (Exception e) {
//                    log.error("[" + LocalDateTime.now() + "]AI响应数据格式：" + chart);
//                    // 更新图表信息表中的图表状态为2-failed
//                    chart.setStatus(ChartStatusEnum.FAILED.getStatus());
//                    setExecMessage(chart, "分析图表数据失败，请尝试重新提交（-2）");
//                    return;
//                }
//                // 保存图表数据
//                chart.setStatus(ChartStatusEnum.SUCCEED.getStatus());
//                chart.setGenChartData(responseMap.get("genChartData"));
//                chart.setGenChartResult(responseMap.get("genChartResult"));
//                chart.setStatus(ChartStatusEnum.SUCCEED.getStatus());
//                chartService.updateById(chart);
//            }
//        }, threadPoolExecutor);
//
//        // 返回生成的图表数据分析结果
//        ChartVO chartVO = new ChartVO();
//        BeanUtils.copyProperties(chart, chartVO);
//        return ResultUtils.success(chartVO);
//    }


    /**
     * 处理AI的响应结果，包含相应的图表数据和图表的分析结论
     */
    private Map<String, String> processResponseData(String responseMessage) {
        String[] split = responseMessage.split("【【【【【");
        if (split.length != 3) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "生成图表出错，请重试！");
        }
        HashMap<String, String> map = new HashMap<>();
        map.put("genChartData", split[1]);  // 这是生成的eCharts图表数据
        map.put("genChartResult", split[2]);    // 这是生成的图表分析结论
        return map;
    }

    private String buildAskStr(String goal, String chartType, String chartData) {
        StringBuilder askStr = new StringBuilder();
        askStr.append("分析需求：");
        askStr.append("\n");
        askStr.append(goal);
        if (StringUtils.isNotBlank(chartType)) {
            askStr.append(", 请使用");
            askStr.append(chartType);
        }
        askStr.append("\n");
        askStr.append("原始数据：");
        askStr.append("\n");
        askStr.append(chartData);
        return askStr.toString();
    }


    @PostMapping("/list")
    public BaseResponse<Page<Chart>> getChartList(@RequestBody ChartRequest chartRequest, HttpServletRequest request) {
        if (chartRequest == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        UserVO userVO = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
        Long pageSize = chartRequest.getPageSize();
        Long page = chartRequest.getCurrent();
        if (pageSize == null || page == null || pageSize <= 0 || page <= 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        LambdaQueryWrapper<Chart> chartQueryWrapper = new LambdaQueryWrapper<>();
        // 如果用户点击搜索，则拼接用户名条件
        chartQueryWrapper.like(StringUtils.isNotBlank(chartRequest.getName()), Chart::getName, chartRequest.getName());
        // 查询属于该用户的图表信息
        chartQueryWrapper.eq(Chart::getUserId, userVO.getId());
        // 排序
        chartQueryWrapper.orderByDesc(Chart::getUpdateTime);

        // 分页展示数据
        Page<Chart> chartVOPage = new Page<>(page, pageSize);
        chartService.page(chartVOPage, chartQueryWrapper);

        return ResultUtils.success(chartVOPage);
    }


    /**
     * 根据id回显图表数据
     */
    @GetMapping("/gid")
    public BaseResponse<ChartVO> getChartById(Long chartId) {
        if (chartId == null || chartId < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Chart chart = chartService.getById(chartId);
        ChartVO chartVO = new ChartVO();
        BeanUtils.copyProperties(chart, chartVO);
        return ResultUtils.success(chartVO);
    }

    /**
     * 根据图表的id更新图表信息，暂不支持修改上传的图表数据
     */
    @PostMapping("/uid/mq")
    public BaseResponse<String> updateById(@RequestBody ChartRequest chartRequest, HttpServletRequest request) {
        Long chartId = chartRequest.getId();
        if (chartId == null || chartId < 0) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        Chart chart = chartService.getById(chartId);

        if (chart == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "更新的图表信息不存在，请刷新页面后重试");
        }
        // 如果只修改了图表名称，那么直接更新返回
        if (chart.getChartType().equals(chartRequest.getChartType())
                && chart.getGoal().equals(chartRequest.getGoal())
                && chart.getName().equals(chartRequest.getName())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "请不要提交未修改的数据！");
        } else if (chart.getChartType().equals(chartRequest.getChartType())
                && chart.getGoal().equals(chartRequest.getGoal())) {
            chart.setName(chartRequest.getName());
            if (!chartService.updateById(chart)) {
                throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在加急修复中...");
            }
            return ResultUtils.success("success");
        }
        String name = chartRequest.getName();
        if (name == null) {
            name = "<未设置图表名称>";
        }
        if (name.length() > 100) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "指定图表名称过长");
        }
        String chartType = chartRequest.getChartType();
        if (chartType == null) {
            chartType = "<未设置图表类型>";
        }
        if (StringUtils.isBlank(chartRequest.getGoal())) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "分析目标不能为空！");
        }
        UserVO user = (UserVO) request.getSession(false).getAttribute(UserConstant.LOGIN_STATE_KEY);
        if (!Objects.equals(user.getId(), chart.getUserId())) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "权限异常，无法修改他人的数据");
        }
        // 做限流操作
        redissonManager.doRate(String.valueOf(user.getId()));
        chart.setName(name);
        chart.setGoal(chartRequest.getGoal());
        chart.setChartType(chartType);
        chart.setStatus(ChartStatusEnum.WAITING.getStatus());   // 设置图表状态为等待中
        chart.setExecMessage(null);
        // 更新图表信息
        if (!chartService.updateById(chart)) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "服务异常，正在加急修复中...");
        }
        // 发送图表id-message到消息队列中
        messageMQProducer.sendMessage(String.valueOf(chart.getId()));
        // 返回异步一阶段的处理成功的结果
        return ResultUtils.success("success");
    }


}
